package org.bonorsoft.modules.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.bonorsoft.common.constant.CommonConstant;
import org.bonorsoft.common.constant.DataBaseConstant;
import org.bonorsoft.common.exception.WilliamBootException;
import org.bonorsoft.common.system.vo.DynamicDataSourceModel;
import org.bonorsoft.common.system.vo.LoginDingUser;
import org.bonorsoft.common.util.*;
import org.bonorsoft.modules.dingding.entity.SysDingUser;
import org.bonorsoft.modules.dingding.mapper.SysDingUserMapper;
import org.bonorsoft.modules.system.entity.SysDataSource;
import org.bonorsoft.modules.system.entity.SysLog;
import org.bonorsoft.modules.system.entity.SysUser;
import org.bonorsoft.modules.system.mapper.SysDictItemMapper;
import org.bonorsoft.modules.system.mapper.SysLogMapper;
import org.bonorsoft.modules.system.mapper.SysUserMapper;
import org.bonorsoft.modules.system.service.ISysDataSourceService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.bonorsoft.common.constant.CacheConstant;
import org.bonorsoft.common.system.api.ISysBaseAPI;
import org.bonorsoft.common.system.vo.LoginUser;
import eu.bitwalker.useragentutils.UserAgent;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.Date;

/**
 * @Description: 底层共通业务API，提供其他独立模块调用
 * @Author: scott
 * @Date:2019-4-20 
 * @Version:V1.0
 */
@Slf4j
@Service
public class SysBaseApiImpl implements ISysBaseAPI {

	/** 当前系统数据库类型 */
	private static String DB_TYPE = "";
	@Resource
	private SysLogMapper sysLogMapper;
	@Resource
	private SysUserMapper userMapper;
	@Resource
	private SysDingUserMapper dingUserMapper;
	@Resource
	private SysDictItemMapper sysDictItemMapper;
	@Autowired
	private ISysDataSourceService dataSourceService;

	@Override
	public void addLog(String userId, Integer logType, Integer operatetype) {
		final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
		SysLog sysLog = new SysLog();
		//获取登录用户信息
		LoginDingUser sysUser = getUserById(userId);
		String username = "";
		if(sysUser!=null){
			sysLog.setUserid(sysUser.getUserid());
			username = sysUser.getName();
			sysLog.setUsername(username);

		}

		String content = "";
		if(operatetype.equals(CommonConstant.OPERATE_TYPE_7)){
			content = "用户名: " + username + ",登录成功！";
		}else{
			content = "用户名: " + username + ",退出成功！";
		}
		//注解上的描述,操作日志内容
		sysLog.setLogContent(content);
		sysLog.setLogType(logType);
		sysLog.setOperateType(operatetype);

		//请求的方法名
		//请求的参数

		try {
			//获取request
			HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
			//设置IP地址
			String ip = IpUtils.getIpAddr(request);
			sysLog.setIp(IpUtils.getIpAddr(request));
			String address = WsAddressUtils.getAddress(ip);
			sysLog.setLoginLocation(address);
		} catch (Exception e) {
			sysLog.setIp("127.0.0.1");
		}

		// 获取客户端操作系统
		String os = userAgent.getOperatingSystem().getName();
		// 获取客户端浏览器
		String browser = userAgent.getBrowser().getName();
		sysLog.setBrowser(browser);
		sysLog.setOs(os);

		sysLog.setCreateTime(new Date());
		//保存系统日志
		sysLogMapper.insert(sysLog);
	}

	@Override
	@Cacheable(cacheNames= CacheConstant.SYS_USERS_CACHE, key="#username")
	public LoginUser getUserByName(String username) {
		if(oConvertUtils.isEmpty(username)) {
			return null;
		}
		LoginUser loginUser = new LoginUser();
		SysUser sysUser = userMapper.getUserByName(username);
		System.out.println(sysUser);
		if(sysUser==null) {
			return null;
		}
		BeanUtils.copyProperties(sysUser, loginUser);
		return loginUser;
	}

	@Override
	@Cacheable(cacheNames= CacheConstant.SYS_USERS_CACHE, key="#user_id")
	public LoginDingUser getUserById(String user_id) {
		if(oConvertUtils.isEmpty(user_id)) {
			return null;
		}
		LoginDingUser loginDingUser = new LoginDingUser();
		SysDingUser dingUser = dingUserMapper.getUserById(user_id);
		if(dingUser==null) {
			return null;
		}
		BeanUtils.copyProperties(dingUser, loginDingUser);
		return loginDingUser;
	}

	@Override
	public String getDatabaseType() throws SQLException {
		if(oConvertUtils.isNotEmpty(DB_TYPE)){
			return DB_TYPE;
		}
		DataSource dataSource = SpringContextUtils.getApplicationContext().getBean(DataSource.class);
		return getDatabaseTypeByDataSource(dataSource);
	}

	/**
	 * 获取数据库类型
	 * @param dataSource
	 * @return
	 * @throws SQLException
	 */
	private String getDatabaseTypeByDataSource(DataSource dataSource) throws SQLException{
		if("".equals(DB_TYPE)) {
			Connection connection = dataSource.getConnection();
			try {
				DatabaseMetaData md = connection.getMetaData();
				String dbType = md.getDatabaseProductName().toLowerCase();
				if(dbType.indexOf("mysql")>=0) {
					DB_TYPE = DataBaseConstant.DB_TYPE_MYSQL;
				}else if(dbType.indexOf("oracle")>=0) {
					DB_TYPE = DataBaseConstant.DB_TYPE_ORACLE;
				}else if(dbType.indexOf("sqlserver")>=0||dbType.indexOf("sql server")>=0) {
					DB_TYPE = DataBaseConstant.DB_TYPE_SQLSERVER;
				}else if(dbType.indexOf("postgresql")>=0) {
					DB_TYPE = DataBaseConstant.DB_TYPE_POSTGRESQL;
				}else {
					throw new WilliamBootException("数据库类型:["+dbType+"]不识别!");
				}
			} catch (Exception e) {
				log.error(e.getMessage(), e);
			}finally {
				connection.close();
			}
		}
		return DB_TYPE;

	}

	@Override
	public DynamicDataSourceModel getDynamicDbSourceByCode(String dbSourceCode) {
		SysDataSource dbSource = dataSourceService.getOne(new LambdaQueryWrapper<SysDataSource>().eq(SysDataSource::getCode, dbSourceCode));
		return new DynamicDataSourceModel(dbSource);
	}

	/** 功能描述:根据type获取学校办学类型
	 *
	 * @vison: 1.0.0
	 * @Author: WilliamYe
	 * @Date: 2020/11/25 22:41
	 */
	@Override
	@Cacheable(value = CacheConstant.SYS_DICT_CACHE_TOTAL,key = "#schoolType")
	public String getSchoolType(String schoolType) {
		log.info("无缓存统计dict的时候调用这里！");
		return sysDictItemMapper.getSchoolType(schoolType);
	}

	/**
	 * 更新登陆者信息
	 * @param loginDingUser
	 */
	@Override
	public void setLoginDingUser(LoginDingUser loginDingUser) {
		Subject subject = SecurityUtils.getSubject();
		PrincipalCollection principalCollection = subject.getPrincipals();
		String realmName = principalCollection.getRealmNames().iterator().next();
		PrincipalCollection newPrincipalCollection = new SimplePrincipalCollection(loginDingUser, realmName);
		// 重新加载Principal
		subject.runAs(newPrincipalCollection);
	}

	@Override
	@Cacheable(value = CacheConstant.SYS_DICT_LEARN_TYPE,key = "#learnType + '-' + #dictId")
	public String getLearnType(String learnType, String dictId) {
		return sysDictItemMapper.getLearnType(learnType, dictId);
	}

}